Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | 'use client'; /** * TicketDetailWrapper - Client component that fetches ticket and manages state */ import React, { useState, useEffect, useCallback } from 'react'; import { SupportTicketWithRelations } from '@/types/support'; import TicketDetail from '@/components/features/support/SupportPortal/TicketDetail'; interface TicketDetailWrapperProps { ticketId: string; } export default function TicketDetailWrapper({ ticketId }: TicketDetailWrapperProps) { const [ticket, setTicket] = useState<SupportTicketWithRelations | null>(null); const [loading, setLoading] = useState(true); const [actionLoading, setActionLoading] = useState(false); const [error, setError] = useState<string | null>(null); const fetchTicket = useCallback(async () => { try { const response = await fetch(`/api/support/tickets/${ticketId}`); if (!response.ok) throw new Error('Failed to fetch ticket'); const data = await response.json(); setTicket(data.ticket); } catch (err) { setError(err instanceof Error ? err.message : 'An error occurred'); } finally { setLoading(false); } }, [ticketId]); useEffect(() => { fetchTicket(); }, [fetchTicket]); const handleSendMessage = async (content: string) => { setActionLoading(true); try { const response = await fetch(`/api/support/tickets/${ticketId}/messages`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ content })}); if (!response.ok) throw new Error('Failed to send message'); await fetchTicket(); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to send message'); } finally { setActionLoading(false); } }; const handleCloseTicket = async () => { setActionLoading(true); try { const response = await fetch(`/api/support/tickets/${ticketId}/close`, { method: 'POST'}); if (!response.ok) throw new Error('Failed to close ticket'); await fetchTicket(); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to close ticket'); } finally { setActionLoading(false); } }; if (loading) { return ( <div className="max-w-4xl mx-auto px-4 py-8"> <div className="animate-spin h-8 w-8 border-4 border-blue-600 border-t-transparent rounded-full mx-auto" /> </div> ); } if (error || !ticket) { return ( <div className="max-w-4xl mx-auto px-4 py-8"> <div className="bg-red-50 text-red-700 px-4 py-3 rounded-lg"> {error || 'Ticket not found'} </div> </div> ); } const showSurvey = ticket.status === 'RESOLVED' && !ticket.survey; return ( <TicketDetail ticket={ticket} onSendMessage={handleSendMessage} onCloseTicket={handleCloseTicket} isLoading={actionLoading} showSurvey={showSurvey} /> ); } |